﻿using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using up7.db.database.up7.sql;
using up7.db.model;
using up7.db.sql;
using up7.db.utils;

namespace up7.db.biz
{/// <summary>
 /// 解析层级信息文件
 /// 用法
 /// FolderSchemaDB fs = new FolderSchemaDB();
 /// fs.save(dir);
 /// </summary>
    public class FolderSchemaDB
    {
        public FileInf m_root;
        public List<FileInf> m_files;
        public List<FileInf> m_folders;
        /// <summary>
        /// 路径字段，路径和目录信息
        /// </summary>
        public Dictionary<string, FileInf> m_dirs;//pathSvr,fd

        public FolderSchemaDB()
        {

        }

        /// <summary>
        /// 分析文件表中的目录信息
        /// </summary>
        public void parseParent()
        {
            foreach (FileInf file in this.m_files)
            {
                FileInf dir = new FileInf();
                dir.id = file.pid;
                dir.uid = this.m_root.uid;
                dir.pidRoot = file.pidRoot;
                dir.pathSvr = PathTool.parentDir(file.pathSvr);
                dir.pathRel = dir.pathSvr.Replace(this.m_root.pathSvr, "");
                dir.nameLoc = PathTool.getName(dir.pathSvr);//取目录名称
                dir.nameSvr = dir.nameLoc;
                dir.fdChild = true;
                dir.complete = true;

                //不存在->添加
                if (!this.m_dirs.ContainsKey(dir.pathSvr))
                {
                    this.m_folders.Add(dir);
                    this.m_dirs.Add(dir.pathSvr, dir);
                }
            }
        }

        /// <summary>
        /// 分析目录表中的子目录信息
        /// </summary>
        public void parseDirs()
        {
            for (int i = 0, l = this.m_folders.Count; i < l; ++i)
            {
                var file = this.m_folders[i];
                String dir = file.pathSvr;
                //依次取子目录并保存
                int pos = dir.IndexOf("/", this.m_root.pathSvr.Length);
                while (-1 != pos)
                {
                    FileInf fd = new FileInf();
                    fd.uid = this.m_root.uid;
                    fd.pathSvr = dir.Substring(0, pos);
                    fd.pidRoot = this.m_root.id;
                    fd.nameLoc = PathTool.getName(fd.pathSvr);
                    fd.nameSvr = fd.nameLoc;
                    fd.pathRel = fd.pathSvr.Replace(this.m_root.pathSvr, "");
                    fd.complete = true;
                    fd.fdChild = true;

                    //目录不存在->添加到目录表
                    if (!this.m_dirs.ContainsKey(fd.pathSvr))
                    {
                        fd.id = Guid.NewGuid().ToString("N");
                        this.m_folders.Add(fd);//添加目录
                        this.m_dirs.Add(fd.pathSvr, fd);//添加字典
                    }

                    pos = dir.IndexOf("/", pos + 1);
                }
            }
        }

        /// <summary>
        /// 更新所有子目录，子文件PID
        /// </summary>
        protected void updatePID()
        {
            //更新子目录pid
            for (int i = 1, l = this.m_folders.Count; i < l; ++i)
            {
                var fd = this.m_folders[i];
                String dir = fd.parentDir();
                FileInf pfd = this.m_dirs[dir];
                fd.pid = pfd.id;
            }

            //更新子文件PID
            for (int i = 0, l = this.m_files.Count; i < l; ++i)
            {
                var f = this.m_files[i];
                String dir = f.parentDir();
                FileInf fd = this.m_dirs[dir];
                f.pid = fd.id;
            }
        }

        /// <summary>
        /// 更新文件相对路径,提供给文件管理器使用
        ///     1.增加根目录前缀
        /// </summary>
        protected void updatePathRel()
        {
            for (int i = 0, l = this.m_folders.Count; i < l; ++i)
            {
                var fd = this.m_folders[i];
                if (!string.IsNullOrEmpty(fd.pid))
                    //更新相对路径->增加根目录前缀
                    fd.pathRel = PathTool.combin(this.m_root.pathRel, fd.pathRel);
            }

            for (int i = 0, l = this.m_files.Count; i < l; ++i)
            {
                var f = this.m_files[i];
                f.pathRel = PathTool.combin(this.m_root.pathRel, f.pathRel);
            }
        }

        protected void loadFiles(FileInf dir)
        {
            Dictionary<string, bool> dic = new Dictionary<string, bool>();
            //加载scheme.txt
            StreamReader sr = new StreamReader(dir.schemaFile());
            string line;
            while ((line = sr.ReadLine()) != null)
            {
                var item = JsonConvert.DeserializeObject<FileInf>(line);
                item.uid = this.m_root.uid;
                //防止重复添加
                if (!dic.ContainsKey(item.id))
                {
                    item.complete = true;
                    item.perSvr = "100%";
                    item.lenSvr = item.lenLoc;
                    item.scaned = true;
                    if (item.fdTask)
                    {
                        this.m_folders.Add(item);
                        this.m_dirs.Add(item.pathSvr, item);
                    }
                    else
                    {
                        item.fdChild = true;
                        item.sizeLoc = item.formatSize(item.lenLoc);
                        item.lenSvr = item.lenLoc;
                        this.m_files.Add(item);
                    }
                    dic.Add(item.id, true);
                }
            }
            sr.Close();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="dir">文件夹信息</param>
        public virtual void save(FileInf dir)
        {
            this.m_root = dir;
            this.m_files = new List<FileInf>();
            this.m_folders = new List<FileInf>();
            this.m_dirs = new Dictionary<string, FileInf>();

            //加载文件信息
            this.loadFiles(dir);

            //分析
            this.parseParent();
            this.parseDirs();
            this.updatePID();
            this.updatePathRel();

            //删除根目录，根目录已经添加到数据表
            this.m_folders.RemoveAt(0);

            //添加目录数据
            SqlFolder.build().addBatch(this.m_folders);

            //添加文件数据
            SqlFile.build().addBatch(this.m_files);
        }

        /// <summary>
        /// 覆盖文件
        /// </summary>
        /// <param name="files"></param>
        protected virtual void cover_files()
        {
            SqlTable.build("up7_files").updates(this.m_files,
                SqlSeter.build().set("f_deleted", true),
                "f_pathRel");
        }

        /// <summary>
        /// 覆盖文件夹
        /// </summary>
        /// <param name="folders"></param>
        protected virtual void cover_folders()
        {
            SqlTable.build("up7_folders").updates(this.m_folders,
                SqlSeter.build().set("f_deleted", true),
                "f_pathRel");
        }


        /// <summary>
        /// 覆盖同名文件，更新相对路径
        /// </summary>
        /// <param name="inf"></param>
        /// <param name="pathParent"></param>
        public void cover()
        {
            this.cover_files();
            this.cover_folders();
        }
    }
}